from urllib.parse import urlparse
import idna
import fnmatch


def extract_domain(url: str) -> str | None:
    """
    从URL中提取纯域名（处理无协议、端口、国际化域名、大小写）
    :param url: 待解析的URL
    :return: 小写格式的域名（解析失败返回None）
    """
    try:
        # 处理无协议URL（如 "www.example.com"）
        parsed = urlparse(url)
        if not parsed.scheme:
            url = f"http://{url}"
            parsed = urlparse(url)

        # 提取域名（去掉端口）
        netloc = parsed.netloc.strip()
        if not netloc:
            return None
        host = netloc.split(":", 1)[0]  # 分割端口（如 example.com:8080 → example.com）

        # 处理国际化域名（如 xn--xxx → 中文域名）
        host_ascii = idna.encode(host, strict=False).decode("ascii")
        host_unicode = idna.decode(host_ascii)

        # 统一转小写
        return host_unicode.lower()
    except Exception:
        return None
    
def match_domain_rule(domain: str | None, rules: list[str]) -> bool:
    """
    检查域名是否匹配规则列表（支持通配符*）
    :param domain: 提取的域名（None则不匹配）
    :param rules: 域名规则列表（如 ["*.example.com", "google.*"]）
    :return: 匹配返回True，否则False
    """
    if domain is None or not rules:
        return False

    # 统一小写处理大小写敏感问题
    domain_lower = domain.lower()
    valid_rules = [rule.strip().lower() for rule in rules if rule.strip()]

    # 遍历规则匹配（fnmatch是Python内置成熟的通配符匹配工具）
    for rule in valid_rules:
        if fnmatch.fnmatch(domain_lower, rule):
            return True
    return False

def filter_url(url: str, rules: list[str]) -> bool:
    """
    核心过滤函数：提取URL域名并匹配规则
    :param url: 待过滤的URL
    :param rules: 域名规则列表（支持*通配符）
    :return: 符合规则返回True，否则False
    """
    domain = extract_domain(url)
    return match_domain_rule(domain, rules)